package com.approval.service;

import com.approval.dto.*;
import com.approval.entity.*;
import com.approval.exception.BusinessException;
import com.approval.mapper.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户管理服务
 */
@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Autowired
    private PasswordPolicyMapper passwordPolicyMapper;
    
    @Autowired
    private UserPasswordHistoryMapper passwordHistoryMapper;
    
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    /**
     * 创建用户
     */
    public UserResponse createUser(UserCreateRequest request) {
        // 验证用户名是否已存在
        if (userMapper.selectByUsername(request.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }
        
        // 验证邮箱是否已存在
        if (StringUtils.hasText(request.getEmail()) && 
            userMapper.selectByEmail(request.getEmail()) != null) {
            throw new BusinessException("邮箱已存在");
        }
        
        // 验证员工ID是否已存在
        if (StringUtils.hasText(request.getEmployeeId()) && 
            userMapper.selectProfileByEmployeeId(request.getEmployeeId()) != null) {
            throw new BusinessException("员工ID已存在");
        }
        
        // 验证密码策略
        validatePassword(request.getPassword());
        
        // 创建用户
        User user = new User();
        BeanUtils.copyProperties(request, user);
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        userMapper.insert(user);
        
        // 创建用户扩展信息
        if (hasProfileInfo(request)) {
            UserProfile profile = new UserProfile();
            profile.setUserId(user.getId());
            BeanUtils.copyProperties(request, profile);
            
            // 设置密码过期时间
            PasswordPolicy policy = passwordPolicyMapper.selectByStatus(1);
            if (policy != null && policy.getPasswordExpireDays() != null) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_MONTH, policy.getPasswordExpireDays());
                profile.setPasswordExpireDate(calendar.getTime());
            }
            
            profile.setCreateTime(new Date());
            profile.setUpdateTime(new Date());
            userMapper.insertProfile(profile);
        }
        
        // 分配角色
        if (request.getRoleIds() != null && !request.getRoleIds().isEmpty()) {
            assignRolesToUser(user.getId(), request.getRoleIds());
        }
        
        // 保存密码历史
        savePasswordHistory(user.getId(), user.getPassword());
        
        return convertToUserResponse(user);
    }
    
    /**
     * 更新用户
     */
    public UserResponse updateUser(Long userId, UserUpdateRequest request) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证邮箱是否已被其他用户使用
        if (StringUtils.hasText(request.getEmail()) && 
            !request.getEmail().equals(user.getEmail()) &&
            userMapper.selectByEmail(request.getEmail()) != null) {
            throw new BusinessException("邮箱已被其他用户使用");
        }
        
        // 验证员工ID是否已被其他用户使用
        if (StringUtils.hasText(request.getEmployeeId())) {
            UserProfile existingProfile = userMapper.selectProfileByEmployeeId(request.getEmployeeId());
            if (existingProfile != null && !existingProfile.getUserId().equals(userId)) {
                throw new BusinessException("员工ID已被其他用户使用");
            }
        }
        
        // 更新用户基本信息
        BeanUtils.copyProperties(request, user, "id", "username", "password", "createTime");
        user.setUpdateTime(new Date());
        userMapper.update(user);
        
        // 更新用户扩展信息
        UserProfile profile = userMapper.selectProfileByUserId(userId);
        if (profile == null && hasProfileInfo(request)) {
            profile = new UserProfile();
            profile.setUserId(userId);
        }
        
        if (profile != null) {
            BeanUtils.copyProperties(request, profile, "id", "userId", "createTime");
            profile.setUpdateTime(new Date());
            if (profile.getId() == null) {
                profile.setCreateTime(new Date());
                userMapper.insertProfile(profile);
            } else {
                userMapper.updateProfile(profile);
            }
        }
        
        // 更新角色
        if (request.getRoleIds() != null) {
            updateUserRoles(userId, request.getRoleIds());
        }
        
        return convertToUserResponse(user);
    }
    
    /**
     * 删除用户
     */
    public void deleteUser(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查是否为超级管理员
        if (isSuperAdmin(user)) {
            throw new BusinessException("不能删除超级管理员");
        }
        
        userMapper.deleteById(userId);
    }
    
    /**
     * 根据ID获取用户
     */
    public UserResponse getUserById(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        return convertToUserResponse(user);
    }
    
    /**
     * 分页查询用户
     */
    public PageResponse<UserResponse> getUsers(PageRequestDto pageRequest, String keyword, String department, Integer status) {
        int offset = (pageRequest.getPage() - 1) * pageRequest.getSize();
        List<User> users = userMapper.selectWithConditions(keyword, department, status, offset, pageRequest.getSize());
        long total = userMapper.countWithConditions(keyword, department, status);
        
        List<UserResponse> userResponses = users.stream()
            .map(this::convertToUserResponse)
            .collect(Collectors.toList());
        
        return new PageResponse<>(userResponses, pageRequest.getPage(), pageRequest.getSize(), total);
    }
    
    /**
     * 启用/禁用用户
     */
    public void updateUserStatus(Long userId, Integer status) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        if (isSuperAdmin(user) && status == 0) {
            throw new BusinessException("不能禁用超级管理员");
        }
        
        user.setStatus(status);
        user.setUpdateTime(new Date());
        userMapper.update(user);
    }
    
    /**
     * 重置用户密码
     */
    public void resetUserPassword(PasswordResetRequest request) {
        User user = userMapper.selectById(request.getUserId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        validatePassword(request.getNewPassword());
        
        String encodedPassword = passwordEncoder.encode(request.getNewPassword());
        user.setPassword(encodedPassword);
        user.setUpdateTime(new Date());
        userMapper.update(user);
        
        // 保存密码历史
        savePasswordHistory(user.getId(), encodedPassword);
        
        // 更新密码过期时间
        updatePasswordExpireDate(user.getId());
    }
    
    /**
     * 修改密码
     */
    public void changePassword(Long userId, PasswordChangeRequest request) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证原密码
        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            throw new BusinessException("原密码不正确");
        }
        
        // 验证新密码
        validatePassword(request.getNewPassword());
        
        // 验证密码历史
        validatePasswordHistory(userId, request.getNewPassword());
        
        String encodedPassword = passwordEncoder.encode(request.getNewPassword());
        user.setPassword(encodedPassword);
        user.setUpdateTime(new Date());
        userMapper.update(user);
        
        // 保存密码历史
        savePasswordHistory(user.getId(), encodedPassword);
        
        // 更新密码过期时间
        updatePasswordExpireDate(user.getId());
    }
    
    /**
     * 批量操作用户
     */
    public void batchOperation(BatchUserOperationRequest request) {
        List<User> users = userMapper.selectByIds(request.getUserIds());
        
        for (User user : users) {
            if (isSuperAdmin(user)) {
                continue; // 跳过超级管理员
            }
            
            switch (request.getOperation()) {
                case "enable":
                    user.setStatus(1);
                    break;
                case "disable":
                    user.setStatus(0);
                    break;
                case "delete":
                    userMapper.deleteById(user.getId());
                    continue;
            }
            
            if (!"delete".equals(request.getOperation())) {
                user.setUpdateTime(new Date());
                userMapper.update(user);
            }
        }
    }
    
    /**
     * 获取用户权限预览
     */
    public UserPermissionPreviewResponse getUserPermissionPreview(Long userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        List<Permission> allPermissions = permissionMapper.selectByUserId(userId);
        
        List<PermissionResponse> menuPermissions = allPermissions.stream()
            .filter(p -> "menu".equals(p.getPermissionType()))
            .map(this::convertToPermissionResponse)
            .collect(Collectors.toList());
        
        List<PermissionResponse> operationPermissions = allPermissions.stream()
            .filter(p -> "operation".equals(p.getPermissionType()))
            .map(this::convertToPermissionResponse)
            .collect(Collectors.toList());
        
        List<PermissionResponse> dataPermissions = allPermissions.stream()
            .filter(p -> "data".equals(p.getPermissionType()))
            .map(this::convertToPermissionResponse)
            .collect(Collectors.toList());
        
        List<String> allPermissionCodes = allPermissions.stream()
            .map(Permission::getPermissionCode)
            .collect(Collectors.toList());
        
        UserPermissionPreviewResponse response = new UserPermissionPreviewResponse();
        response.setUserId(user.getId());
        response.setUsername(user.getUsername());
        response.setName(user.getName());
        response.setRoles(roleMapper.selectByUserId(userId).stream().map(this::convertToRoleResponse).collect(Collectors.toList()));
        response.setMenuPermissions(menuPermissions);
        response.setOperationPermissions(operationPermissions);
        response.setDataPermissions(dataPermissions);
        response.setAllPermissions(allPermissionCodes);
        
        return response;
    }
    
    // 私有方法
    
    private void assignRolesToUser(Long userId, List<Long> roleIds) {
        // 删除现有角色
        userRoleMapper.deleteByUserId(userId);
        
        // 分配新角色
        for (Long roleId : roleIds) {
            Role role = roleMapper.selectById(roleId);
            if (role == null) {
                throw new BusinessException("角色不存在: " + roleId);
            }
            
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRole.setCreateTime(new Date());
            userRoleMapper.insert(userRole);
        }
    }
    
    private void updateUserRoles(Long userId, List<Long> roleIds) {
        if (roleIds.isEmpty()) {
            userRoleMapper.deleteByUserId(userId);
        } else {
            assignRolesToUser(userId, roleIds);
        }
    }
    
    private void validatePassword(String password) {
        PasswordPolicy policy = passwordPolicyMapper.selectByStatus(1);
        if (policy == null) return;
        
        if (password.length() < policy.getMinLength()) {
            throw new BusinessException("密码长度不能少于" + policy.getMinLength() + "位");
        }
        
        if (password.length() > policy.getMaxLength()) {
            throw new BusinessException("密码长度不能超过" + policy.getMaxLength() + "位");
        }
        
        if (policy.getRequireUppercase() && !password.matches(".*[A-Z].*")) {
            throw new BusinessException("密码必须包含大写字母");
        }
        
        if (policy.getRequireLowercase() && !password.matches(".*[a-z].*")) {
            throw new BusinessException("密码必须包含小写字母");
        }
        
        if (policy.getRequireDigits() && !password.matches(".*\\d.*")) {
            throw new BusinessException("密码必须包含数字");
        }
        
        if (policy.getRequireSpecialChars() && !password.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?].*")) {
            throw new BusinessException("密码必须包含特殊字符");
        }
    }
    
    private void validatePasswordHistory(Long userId, String newPassword) {
        PasswordPolicy policy = passwordPolicyMapper.selectByStatus(1);
        if (policy == null || policy.getPasswordHistoryCount() == null) return;
        
        String encodedPassword = passwordEncoder.encode(newPassword);
        if (passwordHistoryMapper.existsByUserIdAndPasswordHash(userId, encodedPassword)) {
            throw new BusinessException("新密码不能与最近" + policy.getPasswordHistoryCount() + "次使用的密码相同");
        }
    }
    
    private void savePasswordHistory(Long userId, String passwordHash) {
        UserPasswordHistory history = new UserPasswordHistory();
        history.setUserId(userId);
        history.setPasswordHash(passwordHash);
        history.setCreateTime(new Date());
        passwordHistoryMapper.insert(history);
        
        // 清理旧密码历史
        PasswordPolicy policy = passwordPolicyMapper.selectByStatus(1);
        if (policy != null && policy.getPasswordHistoryCount() != null) {
            passwordHistoryMapper.deleteOldPasswordHistory(userId, policy.getPasswordHistoryCount());
        }
    }
    
    private void updatePasswordExpireDate(Long userId) {
        PasswordPolicy policy = passwordPolicyMapper.selectByStatus(1);
        if (policy == null || policy.getPasswordExpireDays() == null) return;
        
        UserProfile profile = userMapper.selectProfileByUserId(userId);
        if (profile == null) {
            profile = new UserProfile();
            profile.setUserId(userId);
        }
        
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, policy.getPasswordExpireDays());
        profile.setPasswordExpireDate(calendar.getTime());
        profile.setUpdateTime(new Date());
        
        if (profile.getId() == null) {
            profile.setCreateTime(new Date());
            userMapper.insertProfile(profile);
        } else {
            userMapper.updateProfile(profile);
        }
    }
    
    private boolean hasProfileInfo(UserCreateRequest request) {
        return StringUtils.hasText(request.getEmployeeId()) ||
               StringUtils.hasText(request.getDepartmentCode()) ||
               StringUtils.hasText(request.getPositionCode()) ||
               request.getManagerId() != null ||
               request.getHireDate() != null ||
               request.getExpireDate() != null;
    }
    
    private boolean hasProfileInfo(UserUpdateRequest request) {
        return StringUtils.hasText(request.getEmployeeId()) ||
               StringUtils.hasText(request.getDepartmentCode()) ||
               StringUtils.hasText(request.getPositionCode()) ||
               request.getManagerId() != null ||
               request.getHireDate() != null ||
               request.getExpireDate() != null;
    }
    
    private boolean isSuperAdmin(User user) {
        List<Role> roles = roleMapper.selectByUserId(user.getId());
        return roles.stream()
            .anyMatch(role -> "SUPER_ADMIN".equals(role.getRoleCode()));
    }
    
    private UserResponse convertToUserResponse(User user) {
        UserResponse response = new UserResponse();
        BeanUtils.copyProperties(user, response);
        
        // 设置扩展信息
        UserProfile profile = userMapper.selectProfileByUserId(user.getId());
        if (profile != null) {
            BeanUtils.copyProperties(profile, response);
            
            // 设置上级姓名
            if (profile.getManagerId() != null) {
                User manager = userMapper.selectById(profile.getManagerId());
                if (manager != null) {
                    response.setManagerName(manager.getName());
                }
            }
        }
        
        // 设置角色信息
        List<Role> roles = roleMapper.selectByUserId(user.getId());
        response.setRoles(roles.stream()
            .map(this::convertToRoleResponse)
            .collect(Collectors.toList()));
        
        // 设置权限信息
        List<Permission> permissions = permissionMapper.selectByUserId(user.getId());
        response.setPermissions(permissions.stream()
            .map(this::convertToPermissionResponse)
            .collect(Collectors.toList()));
        
        return response;
    }
    
    private RoleResponse convertToRoleResponse(Role role) {
        RoleResponse response = new RoleResponse();
        BeanUtils.copyProperties(role, response);
        
        // 设置父角色名称
        if (role.getParentId() != null) {
            Role parentRole = roleMapper.selectById(role.getParentId());
            if (parentRole != null) {
                response.setParentRoleName(parentRole.getRoleName());
            }
        }
        
        // 设置用户数量
        response.setUserCount(userRoleMapper.countByRoleId(role.getId()));
        
        return response;
    }
    
    private PermissionResponse convertToPermissionResponse(Permission permission) {
        PermissionResponse response = new PermissionResponse();
        BeanUtils.copyProperties(permission, response);
        
        // 设置父权限名称
        if (permission.getParentId() != null) {
            Permission parentPermission = permissionMapper.selectById(permission.getParentId());
            if (parentPermission != null) {
                response.setParentPermissionName(parentPermission.getPermissionName());
            }
        }
        
        // 设置角色数量
        response.setRoleCount(rolePermissionMapper.countByPermissionId(permission.getId()));
        
        return response;
    }
    
    /**
     * 获取当前用户
     */
    public User getCurrentUser() {
        // 这里需要根据实际的认证方式实现
        // 临时返回一个默认用户
        return userMapper.selectById(1L);
    }
    
    /**
     * 用户登录
     */
    public User login(LoginRequest request) {
        User user = userMapper.selectByUsername(request.getUsername());
        if (user == null) {
            throw new BusinessException("用户名或密码错误");
        }
        
        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        
        if (user.getStatus() != 1) {
            throw new BusinessException("用户已被禁用");
        }
        
        return user;
    }
    
    /**
     * 用户注册
     */
    public User register(RegisterRequest request) {
        if (userMapper.existsByUsername(request.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        
        if (userMapper.existsByEmail(request.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }
        
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setName(request.getName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setStatus(1);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        
        userMapper.insert(user);
        return user;
    }
    
    /**
     * 获取所有用户
     */
    public List<User> getAllUsers() {
        return userMapper.selectAll();
    }
}